package com.sherler.statics;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sherler.data.groups.Group;
import com.sherler.data.groups.KeyCount;
import com.sherler.data.groups.KeyCountList;
import com.sherler.statics.jpa.Cons000016Repository;
import com.sherler.statics.jpa.Cons000300Repository;
import com.sherler.statics.jpa.Cons000905Repository;
import com.sherler.statics.jpa.StockInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.RangeFacet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.repository.CrudRepository;
import org.springframework.scheduling.annotation.EnableAsync;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * Created by GeorgeSherler on 2017/5/21.
 */
@SpringBootApplication
@EnableAsync
public class SolrAnalyze implements CommandLineRunner {
    private Group<String,String> cons000016Group=new Group<>();
    private Group<String,String> cons000300Group=new Group<>();
    private Group<String,String> cons000905Group=new Group<>();

    private String[] period1={"2016-5-1T00:00:00Z","2016-6-11T00:00:00Z"};
    private String[] period2={"2016-6-12T00:00:00Z","2016-12-11T00:00:00Z"};
    private String[] period3={"2016-12-12T00:00:00Z","2017-4-30T00:00:00Z"};

    @Autowired
    public Cons000016Repository cons000016Repository;
    @Autowired
    public Cons000300Repository cons000300Repository;
    @Autowired
    public Cons000905Repository cons000905Repository;

    private ArrayList<StockInfo> stockInfos=new ArrayList<>();

    private boolean amongThePeriod(String dateStr,String start,String end){
        if(dateStr==null||start==null||end==null){
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        try{
            start = start.replace("T"," ").replace("Z","");
            end = end.replace("T"," ").replace("Z","");
            dateStr = dateStr.replace("T"," ").replace("Z","");
            Date startDate=sdf.parse(start);
            Date endDate= sdf.parse(end);
            Date date=sdf.parse(dateStr);
            if(startDate.getTime()<endDate.getTime()){
                if(date.getTime()>=startDate.getTime()&&date.getTime()<=endDate.getTime())
                {
                    return true;
                }
            }
        }catch (Exception e){
            System.out.println(e);
        }
        return false;
    }

    public void run(String... args) throws Exception{
        getStockInfos();
        System.out.println("stock info fetched:"+stockInfos.size());
        System.out.println();
        KeyCountList<String> cons000905=new KeyCountList<>();
        KeyCountList<String> cons000016=new KeyCountList<>();
        KeyCountList<String> cons000300=new KeyCountList<>();
        for(StockInfo stockInfo:stockInfos){
            KeyCountList<String> dateKeyCountList=getHexunDailyStatics(new String[]{stockInfo.getConstituentCode(),stockInfo.getConstituentName()});
            switch (stockInfo.getStrategy()){
                case "000905cons":
                    cons000905Group.put(stockInfo.getConstituentCode(),dateKeyCountList);
                    break;
                case "000016cons":
                    cons000016Group.put(stockInfo.getConstituentCode(),dateKeyCountList);
                    break;
                case "000300cons":
                    cons000300Group.put(stockInfo.getConstituentCode(),dateKeyCountList);
                    break;
            }
        }
        for(StockInfo stockInfo:stockInfos){
            ArrayList<String[]> periods=new ArrayList<>();
            if(stockInfo.getPeriodOne()==1)
            {
                periods.add(period1);
            }
            if(stockInfo.getPeriodTwo()==1)
            {
                periods.add(period2);
            }
            if(stockInfo.getPeriodThree()==1)
            {
                periods.add(period3);
            }
            switch (stockInfo.getStrategy()){
                case "000905cons":
                    for(KeyCount<String> dateKeyCount:cons000905Group.get(stockInfo.getConstituentCode())){
                        for(String[] period:periods)
                        {
                            if(amongThePeriod(dateKeyCount.getKey(),period[0],period[1])){
                                cons000905.add(dateKeyCount);
                            }
                        }
                    }
                    break;
                case "000016cons":
                    for(KeyCount<String> dateKeyCount:cons000016Group.get(stockInfo.getConstituentCode())){
                        for(String[] period:periods)
                        {
                            if(amongThePeriod(dateKeyCount.getKey(),period[0],period[1])){
                                cons000016.add(dateKeyCount);
                            }
                        }
                    }
                    break;
                case "000300cons":
                    for(KeyCount<String> dateKeyCount:cons000300Group.get(stockInfo.getConstituentCode())){
                        for(String[] period:periods)
                        {
                            if(amongThePeriod(dateKeyCount.getKey(),period[0],period[1])){
                                cons000300.add(dateKeyCount);
                            }
                        }
                    }
                    break;
            }
        }
        writeKeyCountList(cons000905,"total","000905cons_statistics");
        writeKeyCountList(cons000016,"total","000016cons_statistics");
        writeKeyCountList(cons000300,"total","000300cons_statistics");
        writeGroup(cons000905Group,"total","000905cons_detail");
        writeGroup(cons000016Group,"total","000016cons_detail");
        writeGroup(cons000300Group,"total","000300cons_detail");
    }
    private void writeKeyCountList(KeyCountList<String> keyCountList,String dir,String fileName){
        if(dir==null||fileName==null||dir.trim().length()<1||fileName.trim().length()<1)
        {
            return;
        }
        try {
            String childRootPath="..\\"+dir;
            File folder =new File(childRootPath);
            if(folder.exists() && folder.isDirectory()? true : folder.mkdirs()) {
            }
            File file = new File("..\\"+dir+"\\"+fileName+".json");
            // if file doesnt exists, then create it
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            System.out.println("output file: "+file.getAbsolutePath());
            OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(file),"utf-8");
            BufferedWriter bw = new BufferedWriter(fw);
            JSONArray jsonObject=new JSONArray();
            jsonObject.addAll(keyCountList);
            String json= jsonObject.toString();
            bw.write(json);
            bw.close();
            //System.out.println("Write Done: "+id);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void writeGroup(Group<String,String> group,String dir,String fileName){
        if(dir==null||fileName==null||dir.trim().length()<1||fileName.trim().length()<1)
        {
            return;
        }
        try {
            String childRootPath="..\\"+dir;
            File folder =new File(childRootPath);
            if(folder.exists() && folder.isDirectory()? true : folder.mkdirs()) {
            }
            File file = new File("..\\"+dir+"\\"+fileName+".json");
            // if file doesnt exists, then create it
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            System.out.println("output file: "+file.getAbsolutePath());
            OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(file),"utf-8");
            BufferedWriter bw = new BufferedWriter(fw);
            JSONObject jsonObject=new JSONObject();
            jsonObject.putAll(group);
            String json= jsonObject.toString();
            bw.write(json);
            bw.close();
            //System.out.println("Write Done: "+id);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void getStockInfos(){
        getStockInfoFromOneRepo(cons000016Repository);
        getStockInfoFromOneRepo(cons000300Repository);
        getStockInfoFromOneRepo(cons000905Repository);
    }
    private void getStockInfoFromOneRepo(CrudRepository crudRepository){
        Iterator<StockInfo> stockInfoIterator=crudRepository.findAll().iterator();
        while(stockInfoIterator.hasNext()){
            stockInfos.add(stockInfoIterator.next());
        }
    }


    private KeyCountList<String> getHexunDailyStatics(String[] words){
        String queryStr=null;
        if(words==null)
        {
            return null;
        }

        queryStr = "(title_cn_txt:\""+StringUtils.join(words,"\") OR (title_cn_txt:\"") + "\")"+"OR (content_cn_txt:\""+StringUtils.join(words,"\") OR (content_cn_txt:\"") + "\")";
        SolrQuery solrQuery=new SolrQuery();
        solrQuery.setQuery(queryStr);
        solrQuery.setFacet(true);
        solrQuery.add("facet.range", "news_date");
        solrQuery.set("f.news_date.facet.range.start", "2016-5-1T00:00:00Z");
        solrQuery.set("f.news_date.facet.range.end", "2017-4-30T00:00:00Z");
        solrQuery.set("f.news_date.facet.range.gap", "+1DAY");
        solrQuery.set("f.news_date.facet.mincount", 0);
//        solrQuery.setFilterQueries("source_cn:股吧");
        QueryResponse queryResponse=null;
        try{
             queryResponse = new HttpSolrClient("http://localhost:8983/solr/stock").query(solrQuery, SolrRequest.METHOD.POST);
        }catch (Exception e){
            System.out.println(e);
            return null;
        }
        return analyzeResult(queryResponse);
    }
    private KeyCountList<String> analyzeResult(QueryResponse queryResponse){
        if(queryResponse==null)
        {
            return null;
        }
        KeyCountList<String> dateKeyCountList=new KeyCountList<>();

        List<RangeFacet> rangeFacets=queryResponse.getFacetRanges();
        if(rangeFacets==null||rangeFacets.size()==0)
        {
            return null;
        }
        for(RangeFacet rangeFacet:rangeFacets){
            String field=rangeFacet.getName();
            for(Object countObj:rangeFacet.getCounts())
            {
                RangeFacet.Count count=(RangeFacet.Count)countObj;
                if(count.getValue().trim().length()<1)
                {
                    continue;
                }
                count.getValue();
                dateKeyCountList.add(new KeyCount<String>(count.getValue().trim(),count.getCount()));
            }
        }
        return dateKeyCountList;
    }
    public static void main(String[] args){
        SpringApplication.run(SolrAnalyze.class,args);
    }
}
